package com.dcits;

import java.io.File;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.openqa.selenium.WebDriver;

import com.dcits.business.BaseTest;
import com.dcits.selenium.TestDriver;
import com.dcits.util.DcitsUtil;
import com.dcits.util.logger.Logger;
import com.dcits.util.prop.PropKit;

/**
 * 用例执行类
 * @author xuwangcheng
 * @version 2018.3.22
 *
 */
public class MainTest {
	
	private static final Logger logger = Logger.getLogger(MainTest.class);
	
	/**
	 * <br>
	 * node - java -jar selenium-server-standalone-2.52.0.jar -role node -port 6666 -maxSession 20 -hub http://127.0.0.1:4444/grid/register -Dwebdriver.chrome.driver=C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chromedriver.exe  -browser "browserName=chrome,maxInstances=5"
	 * <hr>
	 * <br>hub - java -jar selenium-server-standalone-2.52.0.jar -role hub -maxSession 40
	 * 
	 * @param args
	 */
	static TestDriver defaultLocalDriver;
	
	//指定使用的配置文件路径
	//public static final String dev_name = "//yanzb"; 
	public static final String dev_name = ""; 
	
	//依次为totalCount/testCount/successCount
	static int[] counts = new int[]{0, 0, 0};
	static List<Map<String, Object>> resultMaps;
	static Object lock = new Object();
	//设置浏览器类型
	static String browserType = TestDriver.BROWSER_CHROME;
	//html报告标题
	static String title = "河北移动Web自动化测试报告";	
	//不执行组名,如果不输入，默认执行所有组
	public static String[] executeGroupName = new String[]{"1"};
	
	public static void main(String[] args) throws MalformedURLException {
		//加载初始化数据,使用方法PropKit.get("phoneNum");
		PropKit.use("com//dcits//config" + dev_name + "//initParameter.properties");
		
		//清理结果文件
		clearResults();
		//清理截图
		clearScreenshots();
		//清理测试报告
		clearReport();
				
		//设置执行文件路径
		System.setProperty("webdriver.chrome.driver","C:\\Users\\Administrator\\AppData\\Local\\Google\\Chrome\\Application\\chromedriver.exe");
		System.setProperty("webdriver.firefox.bin","");
		System.setProperty("webdriver.ie.driver","");
		System.setProperty("webdriver.opera.bin","");
		
		//获取执行列表
		Map<String, List<BaseTest>> testCases = DcitsUtil.getTestCases("com//dcits//config" + dev_name + "//case.properties");
		
		//获取用例总数
		for (List<BaseTest> list:testCases.values()) {
			counts[0] = counts[0] + list.size();
		}
		
		//执行结果
		resultMaps = new ArrayList<Map<String, Object>>();
		
		//开始执行时间				
		String testTime = DcitsUtil.getFormatCurrentTime();							
		
		//开始执行，按case.properties中的分组
		for (List<BaseTest> cases:testCases.values()) {
			//localMode为true时为本地串行执行，localMode为false时为分布式远程执行		
			if (DcitsUtil.LOCAL_MODE) {
				testCaseGroup(cases, new TestDriver(browserType).getDriver());
			} else {
				new Thread(new Runnable() {					
					@Override
					public void run() {
						// TODO Auto-generated method stub
						try {
							testCaseGroup(cases, new TestDriver(browserType).getDriver());
						} catch (MalformedURLException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				}).start();
			}						
		}
		
		//等待并发执行完成
		while (counts[1] < counts[0]) {
			try {
				Thread.sleep(4000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				//e.printStackTrace();
			}
		}
		
		Map<String, Object> reportInfo = new HashMap<String, Object>();
		reportInfo.put("endTime", DcitsUtil.getFormatCurrentTime());
		//关闭数据库连接
		DcitsUtil.closeAllConnection();
		
		logger.info("正在写入结果到excel...");
		//获取测试结果Map写入excel
		String path = DcitsUtil.exportResultExcel(resultMaps);
		if (path != null) {
			logger.info("写入excel完成！ " + path);
		}
		
		reportInfo.put("totalCount", String.valueOf(counts[1]));
		reportInfo.put("successCount", String.valueOf(counts[2]));
		reportInfo.put("testTime", testTime);
		reportInfo.put("browserName", browserType);
		reportInfo.put("title", title);
		logger.info("正在生成测试报告...");
		
		path = DcitsUtil.generateReport(resultMaps, reportInfo);
		if (path != null) {
			logger.info("生成测试报告成功！ " + path);
		}			
	}
	
	/******************************************************************************************************************/
	private static void testCaseGroup(List<BaseTest> cases, WebDriver driver) {
		driver.manage().window().maximize();
		// TODO Auto-generated method stub
		for (BaseTest test:cases) {
			if (test == null) {
				continue;
			}			
			test.setDriver(driver);
			Long beginTime = System.currentTimeMillis();
			logger.info("开始执行测试用例[" + test.getResultMap().get(BaseTest.RESULT_CASE_ATTRIBUTE_NAME) + "]...");
			try {		
				test.execute();
				logger.info("测试用例[" + test.getResultMap().get(BaseTest.RESULT_CASE_ATTRIBUTE_NAME) + "]执行完成!");
				
				synchronized (lock) {
					counts[2] = counts[2] + 1;
				}
				
			} catch (Exception e) {
				// TODO: handle exception
				logger.error("测试用例[" + test.getResultMap().get(BaseTest.RESULT_CASE_ATTRIBUTE_NAME) + "]执行出错!", e);
				//报错自动截图并结束未结束的步骤					
				try {
					test.screenshot();
					test.endStep(false, e.getMessage() == null ? "" : e.getMessage());										
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					logger.info(e.getMessage());
				}				
				test.getResultMap().put(BaseTest.RESULT_MARK_ATTRIBUTE_NAME, "执行出错" + e.getMessage());
				test.getResultMap().put(BaseTest.RESULT_STATUS_ATTRIBUTE_NAME, BaseTest.ERROR_STATUS);
				
			}	
			Long endTime = System.currentTimeMillis();
			test.getResultMap().put(BaseTest.RESULT_FINISH_TIME_ATTRIBUTE_NAME, DcitsUtil.getFormatCurrentTime());
			test.getResultMap().put(BaseTest.RESULT_USE_TIME_ATTRIBUTE_NAME, String.valueOf((endTime - beginTime) / 1000));			
			
			resultMaps.add(test.getResultMap());
			synchronized (lock) {
				counts[1] = counts[1] + 1;
			}
		}
		driver.quit();		
	}

	/**********************************************************************/
	
	
	public static void clearReport() {
		clearFolder(DcitsUtil.REPORT_FILE_PATH);
	}
	
	public static void clearResults() {
		clearFolder(DcitsUtil.RESULT_EXCEL_PATH);
	}
	
	public static void clearScreenshots() {
		clearFolder(DcitsUtil.SCREENSHOT_PATH);
	}
	
	public static void clearFolder(String path) {
		File file = new File(path);
		if (!file.exists()) {
			return;
		}
		
		for (File f:file.listFiles()) {
			f.delete();
		}
	}
}
